#include <string>
#include <cassert>
#include <vector>
#include <ostream>
#include <iostream>
#include <format> //C++20格式化库 很好用
#include <regex>
using namespace std;

//字符串不是一个类型 是basic_string的一个特化类型 是一个类型别名
using stirng = std::basic_string<char>;
using wstirng = std::basic_string<wchar_t>;  //C++98
using u8stirng = std::basic_string<char8_t>; //C++20 需要使用g++ 4.2.cpp -std=c++20 -o a.out编译
using u16stirng = std::basic_string<char16_t>;  //C++11
using u32stirng = std::basic_string<char32_t>;  //C++11
//建议只在开发中使用string 在涉及Unicode 编码转换的时候尽量不要用C++ 目前不太擅长做这种工作改用其它语言比较好
int main()
{
    string str = "abc";
    assert(str[1] == 'b');
    auto p = str.c_str(); //const char *指针 但是末尾会添加\0
    auto p1 = str.data();
    assert(str.starts_with("ab")); //C++20新增接口判断前缀
    assert(str.ends_with("bc")); //C++20新增接口判断前缀
    vector<char> v; //string中字符之间是强关系顺序不能随意调换应该视为一个整体处理 如果只需要字符容器，可以用vector

    //C++11 原始字符串 可以原封不动输出\r\n等转义符
    auto str1 = R"(nier:automata\r\n\t)";
    cout << str1 << endl;
    //如果想输出R()的话 前后加==
    str1 = R"==(R"(nier:automata\r\n\t)")==";
    cout << str1 << endl;

    //C++11新增方法
    cout << stoi("123") << endl;
    cout << stof("123.1") << endl;
    cout << to_string(123) << endl;

    //字面值后缀
    auto str2 = "abc"s; //后面加s 代表是字符串类型 而不是C字符串 可以自动推导出来string
    cout << str2.size() << endl;
    cout << "abc"s.size() << endl;
    // cout << "abc".size() << endl;
    
    /*为了降低使用成本 可以使用string_view 
    1. 它只保存字符串的起始地址和长度 
    2. 它是只读视图只能查看不能修改相当于const string&
    3. 由于使用的是指针所以当心引用内容失效类似weak_ptr
    4. 其使用方式基本与字符串一致
    */
   string_view sv;
   assert(sv.empty());

   sv = "123";
   assert(sv.size() == 3);

    string_view sv1("1234", 3);
    assert(sv.size() == 3);
    assert(sv == "123");

    //可以使用sv后缀代表string_view类型字符串, 直接用auto来推导
    auto sv3 = "123"sv;
    assert(sv3.find("23") != string_view::npos);

    //字符串格式化 格式占位符基本形式{序号:格式标志}
    //https://zhuanlan.zhihu.com/p/632498552
    cout << format("{0:x}-{1}", 16, 56) << endl; //16进制输出

    //如果想输出{} 就只能用{{}}
    cout << format("{{0:x}}-{1}", 16, 56) << endl;

    //正则表达式
    /*
    . 匹配任意的单个字符
    $ 匹配行的末尾
    ^ 匹配行的开头
    () 定义子表达式 可以被引用或者重复
    * 表示元素可以重复任意多次
    + 表示元素可以重复一次或多次
    ? 表示元素可以重复0次或1次
    | 匹配它两侧的元素之一
    [] 定义字符集合
    \ 转义符
    */
    regex reg1{R"(\d+\.\d)", regex_constants::icase|regex_constants::optimize};
    //C++正则表达式有3种算法 分别实现匹配 查找和替换 他们都是只读的 不会改动原字符串
    
    //正则匹配 PCRE标准
    assert(regex_match("a:b", std::regex(R"(^(\w+)\:(\w+)$)")));
    assert(!regex_match("a,b", std::regex(R"(^(\w+)\:(\w+)$)")));

    match_results what = smatch();
    string strs = "neir:automata";
    //第一个参数不能直接传字面量字符串"neir:automata"
    regex_match(strs, what, std::regex(R"(^(\w+)\:(\w+)$)"));
    assert(what[1] == "neir");
    assert(what[2] == "automata");

    auto found = regex_search(strs, what, std::regex(R"(^(\w+)\:(\w+)$)"));
    assert(found);
    assert(!what.empty());
    assert(what[1] == "neir");
    assert(what[2] == "automata");

    assert(regex_search("unix_time", std::regex(R"(^(unix))"))); //检查前缀
    assert(regex_search("abc.com", std::regex(R"(com$)")));      //检查后缀

    auto new_str = regex_replace("god of war"s, std::regex(R"(\w+$)"), "peace");
    cout << new_str << endl;
}